home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Comm / www / tidy_os4.lha / tidy / console / tidy.c < prev   
C/C++ Source or Header  |  2004-07-25  |  25KB  |  770 lines

  1. /*
  2.   tidy.c - HTML TidyLib command line driver
  3.  
  4.   Copyright (c) 1998-2003 World Wide Web Consortium
  5.   (Massachusetts Institute of Technology, European Research 
  6.   Consortium for Informatics and Mathematics, Keio University).
  7.   All Rights Reserved.
  8.  
  9.   CVS Info :
  10.  
  11.     $Author: terry_teague $ 
  12.     $Date: 2004/03/19 02:42:19 $ 
  13.     $Revision: 1.17 $ 
  14. */
  15.  
  16. #include "tidy.h"
  17.  
  18. FILE* errout = NULL;  /* set to stderr */
  19. FILE* txtout = NULL;  /* set to stdout */
  20.  
  21. Bool samefile( ctmbstr filename1, ctmbstr filename2 )
  22. {
  23. #if FILENAMES_CASE_SENSITIVE
  24.     return ( strcmp( filename1, filename2 ) == 0 );
  25. #else
  26.     return ( strcasecmp( filename1, filename2 ) == 0 );
  27. #endif
  28. }
  29.  
  30. void help( TidyDoc tdoc, ctmbstr prog )
  31. {
  32.     printf( "%s [option...] [file...] [option...] [file...]\n", prog );
  33.     printf( "Utility to clean up and pretty print HTML/XHTML/XML\n");
  34.     printf( "see http://tidy.sourceforge.net/\n");
  35.     printf( "\n");
  36.  
  37. #ifdef PLATFORM_NAME
  38.     printf( "Options for HTML Tidy for %s released on %s:\n",
  39.              PLATFORM_NAME, tidyReleaseDate() );
  40. #else
  41.     printf( "Options for HTML Tidy released on %s:\n", tidyReleaseDate() );
  42. #endif
  43.     printf( "\n");
  44.  
  45.     printf( "File manipulation\n");
  46.     printf( "-----------------\n");
  47.     printf( "  -out or -o <file> specify the output markup file\n");
  48.     printf( "  -config <file>    set configuration options from the specified <file>\n");
  49.     printf( "  -f      <file>    write errors to the specified <file>\n");
  50.     printf( "  -modify or -m     modify the original input files\n");
  51.     printf( "\n");
  52.  
  53.     printf( "Processing directives\n");
  54.     printf( "---------------------\n");
  55.     printf( "  -indent  or -i    indent element content\n");
  56.     printf( "  -wrap <column>    wrap text at the specified <column> (default is 68)\n");
  57.     printf( "  -upper   or -u    force tags to upper case (default is lower case)\n");
  58.     printf( "  -clean   or -c    replace FONT, NOBR and CENTER tags by CSS\n");
  59.     printf( "  -bare    or -b    strip out smart quotes and em dashes, etc.\n");
  60.     printf( "  -numeric or -n    output numeric rather than named entities\n");
  61.     printf( "  -errors  or -e    only show errors\n");
  62.     printf( "  -quiet   or -q    suppress nonessential output\n");
  63.     printf( "  -omit             omit optional end tags\n");
  64.     printf( "  -xml              specify the input is well formed XML\n");
  65.     printf( "  -asxml            convert HTML to well formed XHTML\n");
  66.     printf( "  -asxhtml          convert HTML to well formed XHTML\n");
  67.     printf( "  -ashtml           force XHTML to well formed HTML\n");
  68.  
  69. /* TRT */
  70. #if SUPPORT_ACCESSIBILITY_CHECKS
  71.     printf( "  -access <level>   do additional accessibility checks (<level> = 1, 2, 3)\n");
  72. #endif
  73.  
  74.     printf( "\n");
  75.  
  76.     printf( "Character encodings\n");
  77.     printf( "-------------------\n");
  78.     printf( "  -raw              output values above 127 without conversion to entities\n");
  79.     printf( "  -ascii            use US-ASCII for output, ISO-8859-1 for input\n");
  80.     printf( "  -latin0           use US-ASCII for output, ISO-8859-1 for input\n");
  81.     printf( "  -latin1           use ISO-8859-1 for both input and output\n");
  82. #ifndef NO_NATIVE_ISO2022_SUPPORT
  83.     printf( "  -iso2022          use ISO-2022 for both input and output\n");
  84. #endif
  85.     printf( "  -utf8             use UTF-8 for both input and output\n");
  86.     printf( "  -mac              use MacRoman for input, US-ASCII for output\n");
  87.     printf( "  -win1252          use Windows-1252 for input, US-ASCII for output\n");
  88.     printf( "  -ibm858           use IBM-858 (CP850+Euro) for input, US-ASCII for output\n");
  89.  
  90. #if SUPPORT_UTF16_ENCODINGS
  91.     printf( "  -utf16le          use UTF-16LE for both input and output\n");
  92.     printf( "  -utf16be          use UTF-16BE for both input and output\n");
  93.     printf( "  -utf16            use UTF-16 for both input and output\n");
  94. #endif
  95.  
  96. #if SUPPORT_ASIAN_ENCODINGS /* #431953 - RJ */
  97.     printf( "  -big5             use Big5 for both input and output\n"); 
  98.     printf( "  -shiftjis         use Shift_JIS for both input and output\n");
  99.     printf( "  -language <lang>  set the two-letter language code <lang> (for future use)\n");
  100. #endif
  101.     printf( "\n");
  102.  
  103.     printf( "Miscellaneous\n");
  104.     printf( "-------------\n");
  105.     printf( "  -version  or -v   show the version of Tidy\n");
  106.     printf( "  -help, -h or -?   list the command line options\n");
  107.     printf( "  -help-config      list all configuration options\n");
  108.     printf( "  -show-config      list the current configuration settings\n");
  109.     printf( "\n");
  110.     printf( "Use --blah blarg for any configuration option \"blah\" with argument \"blarg\"\n");
  111.     printf( "\n");
  112.  
  113.     printf( "Input/Output default to stdin/stdout respectively\n");
  114.     printf( "Single letter options apart from -f may be combined\n");
  115.     printf( "as in:  tidy -f errs.txt -imu foo.html\n");
  116.     printf( "For further info on HTML see http://www.w3.org/MarkUp\n");
  117.     printf( "\n");
  118. }
  119.  
  120. #define kMaxValFieldWidth 40
  121. static const char* fmt = "%-27.27s %-9.9s  %-40.40s\n";
  122. static const char* valfmt = "%-27.27s %-9.9s %-1.1s%-39.39s\n";
  123. static const char* ul 
  124.         = "=================================================================";
  125.  
  126. void optionhelp( TidyDoc tdoc, ctmbstr prog )
  127. {
  128.     TidyIterator pos = tidyGetOptionList( tdoc );
  129.  
  130.     printf( "\nHTML Tidy Configuration Settings\n\n" );
  131.     printf( "Within a file, use the form:\n\n" ); 
  132.     printf( "wrap: 72\n" );
  133.     printf( "indent: no\n\n" );
  134.     printf( "When specified on the command line, use the form:\n\n" );
  135.     printf( "--wrap 72 --indent no\n\n");
  136.  
  137.     printf( fmt, "Name", "Type", "Allowable values" );
  138.     printf( fmt, ul, ul, ul );
  139.  
  140.     while ( pos )
  141.     {
  142.         TidyOption topt = tidyGetNextOption( tdoc, &pos );
  143.         TidyOptionId optId = tidyOptGetId( topt );
  144.         TidyOptionType optTyp = tidyOptGetType( topt );
  145.  
  146.         tmbstr name = (tmbstr) tidyOptGetName( topt );
  147.         tmbstr type = "String";
  148.         tmbchar tempvals[80] = {0};
  149.         tmbstr vals = &tempvals[0];
  150.  
  151.         if ( tidyOptIsReadOnly(topt) )
  152.             continue;
  153.  
  154.         /* Handle special cases first.
  155.         */
  156.         switch ( optId )
  157.         {
  158.         case TidyIndentContent:
  159. #if SUPPORT_UTF16_ENCODINGS
  160.         case TidyOutputBOM:
  161. #endif
  162.             type = "AutoBool";
  163.             vals = "auto, y/n, yes/no, t/f, true/false, 1/0";
  164.             break;
  165.  
  166.         case TidyDuplicateAttrs:
  167.             type = "enum";
  168.             vals = "keep-first, keep-last";
  169.             break;
  170.  
  171.         case TidyDoctype:
  172.             type = "DocType";
  173.             vals = "auto, omit, strict, loose, transitional,";
  174.             printf( fmt, name, type, vals );
  175.             name = "";
  176.             type = "";
  177.             vals = "user specified fpi (string)";
  178.             break;
  179.  
  180.         case TidyCSSPrefix:
  181.             type = "Name";
  182.             vals = "CSS1 selector";
  183.             break;
  184.  
  185.         case TidyInlineTags:
  186.         case TidyBlockTags:
  187.         case TidyEmptyTags:
  188.         case TidyPreTags:
  189.             type = "Tag names";
  190.             vals = "tagX, tagY, ...";
  191.             break;
  192.  
  193.         case TidyCharEncoding:
  194.         case TidyInCharEncoding:
  195.         case TidyOutCharEncoding:
  196.             type = "Encoding";
  197.             vals = "ascii, latin0, latin1, raw, utf8, iso2022,";
  198.             printf( fmt, name, type, vals );
  199.             name = "";
  200.             type = "";
  201.  
  202. #if SUPPORT_UTF16_ENCODINGS
  203.             vals = "utf16le, utf16be, utf16,";
  204.             printf( fmt, name, type, vals );
  205. #endif
  206. #if SUPPORT_ASIAN_ENCODINGS
  207.             vals = "mac, win1252, ibm858, big5, shiftjis";
  208. #else
  209.             vals = "mac, win1252, ibm858";
  210. #endif
  211.             break;
  212.  
  213.         case TidyNewline:
  214.             type = "enum";
  215.             vals = "LF, CRLF, CR";
  216.             break;
  217.  
  218.         /* General case will handle remaining */
  219.         default:
  220.             switch ( optTyp )
  221.             {
  222.             case TidyBoolean:
  223.                 type = "Boolean";
  224.                 vals = "y/n, yes/no, t/f, true/false, 1/0";
  225.                 break;
  226.  
  227.             case TidyInteger:
  228.                 type = "Integer";
  229.                 if ( optId == TidyWrapLen )
  230.                     vals = "0 (no wrapping), 1, 2, ...";
  231.                 else
  232.                     vals = "0, 1, 2, ...";
  233.                 break;
  234.  
  235.             case TidyString:
  236.                 type = "String";
  237.                 vals = "-";
  238.                 break;
  239.             }
  240.         }
  241.  
  242.         if ( *name || *type || *vals )
  243.             printf( fmt, name, type, vals );
  244.     }
  245. }
  246.  
  247. void optionvalues( TidyDoc tdoc, ctmbstr prog )
  248. {
  249.     TidyIterator pos = tidyGetOptionList( tdoc );
  250.  
  251.     printf( "\nConfiguration File Settings:\n\n" );
  252.     printf( fmt, "Name", "Type", "Current Value" );
  253.     printf( fmt, ul, ul, ul );
  254.  
  255.     while ( pos )
  256.     {
  257.         TidyOption topt = tidyGetNextOption( tdoc, &pos );
  258.         TidyOptionId optId = tidyOptGetId( topt );
  259.         TidyOptionType optTyp = tidyOptGetType( topt );
  260.         Bool isReadOnly = tidyOptIsReadOnly( topt );
  261.  
  262.         Bool bval = no;
  263.         ctmbstr sval = NULL;
  264.         uint ival = 0;
  265.  
  266.         tmbstr name = (tmbstr) tidyOptGetName( topt );
  267.         tmbstr type = "String";
  268.         tmbchar tempvals[80] = {0};
  269.         tmbstr vals = &tempvals[0];
  270.         tmbstr ro   = ( isReadOnly ? "*" : "" );
  271.  
  272.         /* Handle special cases first.
  273.         */
  274.         switch ( optId )
  275.         {
  276.         case TidyIndentContent:
  277. #if SUPPORT_UTF16_ENCODINGS
  278.         case TidyOutputBOM:
  279. #endif
  280.             type = "AutoBool";
  281.             vals = (tmbstr) tidyOptGetCurrPick( tdoc, optId );
  282.             break;
  283.  
  284.         case TidyDuplicateAttrs:
  285.             type = "enum";
  286.             vals = (tmbstr) tidyOptGetCurrPick( tdoc, optId );
  287.             break;
  288.  
  289.         case TidyDoctype:
  290.             sval = (tmbstr) tidyOptGetCurrPick( tdoc, TidyDoctypeMode );
  291.             type = "DocType";
  292.             if ( !sval || *sval == '*' )
  293.                 sval = (tmbstr) tidyOptGetValue( tdoc, TidyDoctype );
  294.             vals = (tmbstr) sval;
  295.             break;
  296.  
  297.         case TidyCSSPrefix:
  298.             type = "Name";
  299.             vals = (tmbstr) tidyOptGetValue( tdoc, TidyCSSPrefix );
  300.             break;
  301.  
  302.         case TidyInlineTags:
  303.         case TidyBlockTags:
  304.         case TidyEmptyTags:
  305.         case TidyPreTags:
  306.             {
  307.                 TidyIterator pos = tidyOptGetDeclTagList( tdoc );
  308.                 type = "Tag names";
  309.                 while ( pos )
  310.                 {
  311.                     vals = (tmbstr) tidyOptGetNextDeclTag(tdoc, optId, &pos);
  312.                     if ( pos )
  313.                     {
  314.                         if ( *name )
  315.                             printf( valfmt, name, type, ro, vals );
  316.                         else
  317.                             printf( fmt, name, type, vals );
  318.                         name = "";
  319.                         type = "";
  320.                     }
  321.                 }
  322.             }
  323.             break;
  324.  
  325.         case TidyCharEncoding:
  326.         case TidyInCharEncoding:
  327.         case TidyOutCharEncoding:
  328.             type = "Encoding";
  329.             sval = tidyOptGetEncName( tdoc, optId );
  330.             vals = (tmbstr) sval;
  331.             break;
  332.  
  333.         case TidyNewline:
  334.             type = "enum";
  335.             vals = (tmbstr) tidyOptGetCurrPick( tdoc, optId );
  336.             break;
  337.  
  338.         /* General case will handle remaining */
  339.         default:
  340.             switch ( optTyp )
  341.             {
  342.             case TidyBoolean:
  343.                 type = "Boolean";   /* curr pick handles inverse */
  344.                 vals = (tmbstr) tidyOptGetCurrPick( tdoc, optId );
  345.                 break;
  346.  
  347.             case TidyInteger:
  348.                 type = "Integer";
  349.                 ival = tidyOptGetInt( tdoc, optId );
  350.                 sprintf( tempvals, "%d", ival );
  351.                 break;
  352.  
  353.             case TidyString:
  354.                 type = "String";
  355.                 vals = (tmbstr) tidyOptGetValue( tdoc, optId );
  356.                 break;
  357.             }
  358.         }
  359.  
  360.         /* fix for http://tidy.sf.net/bug/873921 */
  361.         if ( *name || *type || (vals && *vals) )
  362.         {
  363.             if ( ! vals )
  364.                 vals = "";
  365.             if ( *name )
  366.                 printf( valfmt, name, type, ro, vals );
  367.             else
  368.                 printf( fmt, name, type, vals );
  369.         }
  370.     }
  371.  
  372.     printf( "\n\nValues marked with an *asterisk are calculated \n"
  373.             "internally by HTML Tidy\n\n" );
  374. }
  375.  
  376. void version( TidyDoc tdoc, ctmbstr prog )
  377. {
  378. #ifdef PLATFORM_NAME
  379.     printf( "HTML Tidy for %s released on %s\n",
  380.              PLATFORM_NAME, tidyReleaseDate() );
  381. #else
  382.     printf( "HTML Tidy released on %s\n", tidyReleaseDate() );
  383. #endif
  384. }
  385.  
  386. void unknownOption( TidyDoc tdoc, uint c )
  387. {
  388.     fprintf( errout, "HTML Tidy: unknown option: %c\n", c );
  389. }
  390.  
  391. int main( int argc, char** argv )
  392. {
  393.     ctmbstr prog = argv[0];
  394.     ctmbstr cfgfil = NULL, errfil = NULL, htmlfil = NULL;
  395.     TidyDoc tdoc = tidyCreate();
  396.     int status = 0;
  397.  
  398.     uint contentErrors = 0;
  399.     uint contentWarnings = 0;
  400.     uint optionErrors = 0;
  401.     uint accessWarnings = 0;
  402.  
  403.     errout = stderr;  /* initialize to stderr */
  404.     status = 0;
  405.     
  406. #ifdef CONFIG_FILE
  407.     if ( tidyFileExists(CONFIG_FILE) )
  408.     {
  409.         status = tidyLoadConfig( tdoc, CONFIG_FILE );
  410.         if ( status != 0 )
  411.             fprintf(errout, "Loading config file \"%s\" failed, err = %d\n", CONFIG_FILE, status);
  412.     }
  413. #endif /* CONFIG_FILE */
  414.  
  415.     /* look for env var "HTML_TIDY" */
  416.     /* then for ~/.tidyrc (on platforms defining $HOME) */
  417.  
  418.     if ( cfgfil = getenv("HTML_TIDY") )
  419.     {
  420.         status = tidyLoadConfig( tdoc, cfgfil );
  421.         if ( status != 0 )
  422.             fprintf(errout, "Loading config file \"%s\" failed, err = %d\n", cfgfil, status);
  423.     }
  424. #ifdef USER_CONFIG_FILE
  425.     else if ( tidyFileExists(USER_CONFIG_FILE) )
  426.     {
  427.         status = tidyLoadConfig( tdoc, USER_CONFIG_FILE );
  428.         if ( status != 0 )
  429.             fprintf(errout, "Loading config file \"%s\" failed, err = %d\n", USER_CONFIG_FILE, status);
  430.     }
  431. #endif /* USER_CONFIG_FILE */
  432.  
  433.     /* read command line */
  434.     while ( argc > 0 )
  435.     {
  436.         if (argc > 1 && argv[1][0] == '-')
  437.         {
  438.             /* support -foo and --foo */
  439.             ctmbstr arg = argv[1] + 1;
  440.  
  441.             if ( strcasecmp(arg, "xml") == 0)
  442.                 tidyOptSetBool( tdoc, TidyXmlTags, yes );
  443.  
  444.             else if ( strcasecmp(arg,   "asxml") == 0 ||
  445.                       strcasecmp(arg, "asxhtml") == 0 )
  446.             {
  447.                 tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
  448.             }
  449.             else if ( strcasecmp(arg,   "ashtml") == 0 )
  450.                 tidyOptSetBool( tdoc, TidyHtmlOut, yes );
  451.  
  452.             else if ( strcasecmp(arg, "indent") == 0 )
  453.             {
  454.                 tidyOptSetInt( tdoc, TidyIndentContent, TidyAutoState );
  455.                 if ( tidyOptGetInt(tdoc, TidyIndentSpaces) == 0 )
  456.                     tidyOptResetToDefault( tdoc, TidyIndentSpaces );
  457.             }
  458.             else if ( strcasecmp(arg, "omit") == 0 )
  459.                 tidyOptSetBool( tdoc, TidyHideEndTags, yes );
  460.  
  461.             else if ( strcasecmp(arg, "upper") == 0 )
  462.                 tidyOptSetBool( tdoc, TidyUpperCaseTags, yes );
  463.  
  464.             else if ( strcasecmp(arg, "clean") == 0 )
  465.                 tidyOptSetBool( tdoc, TidyMakeClean, yes );
  466.  
  467.             else if ( strcasecmp(arg, "bare") == 0 )
  468.                 tidyOptSetBool( tdoc, TidyMakeBare, yes );
  469.  
  470.             else if ( strcasecmp(arg, "raw") == 0      ||
  471.                       strcasecmp(arg, "ascii") == 0    ||
  472.                       strcasecmp(arg, "latin0") == 0   ||
  473.                       strcasecmp(arg, "latin1") == 0   ||
  474.                       strcasecmp(arg, "utf8") == 0     ||
  475. #ifndef NO_NATIVE_ISO2022_SUPPORT
  476.                       strcasecmp(arg, "iso2022") == 0  ||
  477. #endif
  478. #if SUPPORT_UTF16_ENCODINGS
  479.                       strcasecmp(arg, "utf16le") == 0  ||
  480.                       strcasecmp(arg, "utf16be") == 0  ||
  481.                       strcasecmp(arg, "utf16") == 0    ||
  482. #endif
  483. #if SUPPORT_ASIAN_ENCODINGS
  484.                       strcasecmp(arg, "shiftjis") == 0 ||
  485.                       strcasecmp(arg, "big5") == 0     ||
  486. #endif
  487.                       strcasecmp(arg, "mac") == 0      ||
  488.                       strcasecmp(arg, "win1252") == 0  ||
  489.                       strcasecmp(arg, "ibm858") == 0 )
  490.             {
  491.                 tidySetCharEncoding( tdoc, arg );
  492.             }
  493.             else if ( strcasecmp(arg, "numeric") == 0 )
  494.                 tidyOptSetBool( tdoc, TidyNumEntities, yes );
  495.  
  496.             else if ( strcasecmp(arg, "modify") == 0 ||
  497.                       strcasecmp(arg, "change") == 0 ||  /* obsolete */
  498.                       strcasecmp(arg, "update") == 0 )   /* obsolete */
  499.             {
  500.                 tidyOptSetBool( tdoc, TidyWriteBack, yes );
  501.             }
  502.             else if ( strcasecmp(arg, "errors") == 0 )
  503.                 tidyOptSetBool( tdoc, TidyShowMarkup, no );
  504.  
  505.             else if ( strcasecmp(arg, "quiet") == 0 )
  506.                 tidyOptSetBool( tdoc, TidyQuiet, yes );
  507.  
  508.             else if ( strcasecmp(arg, "help") == 0 ||
  509.                       strcasecmp(arg,    "h") == 0 || *arg == '?' )
  510.             {
  511.                 help( tdoc, prog );
  512.                 tidyRelease( tdoc );
  513.                 return 0; /* success */
  514.             }
  515.             else if ( strcasecmp(arg, "help-config") == 0 )
  516.             {
  517.                 optionhelp( tdoc, prog );
  518.                 tidyRelease( tdoc );
  519.                 return 0; /* success */
  520.             }
  521.             else if ( strcasecmp(arg, "show-config") == 0 )
  522.             {
  523.                 optionvalues( tdoc, prog );
  524.                 tidyRelease( tdoc );
  525.                 return 0; /* success */
  526.             }
  527.             else if ( strcasecmp(arg, "config") == 0 )
  528.             {
  529.                 if ( argc >= 3 )
  530.                 {
  531.                     ctmbstr post;
  532.  
  533.                     tidyLoadConfig( tdoc, argv[2] );
  534.  
  535.                     /* Set new error output stream if setting changed */
  536.                     post = tidyOptGetValue( tdoc, TidyErrFile );
  537.                     if ( post && (!errfil || !samefile(errfil, post)) )
  538.                     {
  539.                         errfil = post;
  540.                         errout = tidySetErrorFile( tdoc, post );
  541.                     }
  542.  
  543.                     --argc;
  544.                     ++argv;
  545.                 }
  546.             }
  547.  
  548. #if SUPPORT_ASIAN_ENCODINGS
  549.             else if ( strcasecmp(arg, "language") == 0 ||
  550.                       strcasecmp(arg,     "lang") == 0 )
  551.             {
  552.                 if ( argc >= 3 )
  553.                 {
  554.                     tidyOptSetValue( tdoc, TidyLanguage, argv[2] );
  555.                     --argc;
  556.                     ++argv;
  557.                 }
  558.             }
  559. #endif
  560.  
  561.             else if ( strcasecmp(arg, "output") == 0 ||
  562.                       strcasecmp(arg, "-output-file") == 0 ||
  563.                       strcasecmp(arg, "o") == 0 )
  564.             {
  565.                 if ( argc >= 3 )
  566.                 {
  567.                     tidyOptSetValue( tdoc, TidyOutFile, argv[2] );
  568.                     --argc;
  569.                     ++argv;
  570.                 }
  571.             }
  572.             else if ( strcasecmp(arg,  "file") == 0 ||
  573.                       strcasecmp(arg, "-file") == 0 ||
  574.                       strcasecmp(arg,     "f") == 0 )
  575.             {
  576.                 if ( argc >= 3 )
  577.                 {
  578.                     errfil = argv[2];
  579.                     errout = tidySetErrorFile( tdoc, errfil );
  580.                     --argc;
  581.                     ++argv;
  582.                 }
  583.             }
  584.             else if ( strcasecmp(arg,  "wrap") == 0 ||
  585.                       strcasecmp(arg, "-wrap") == 0 ||
  586.                       strcasecmp(arg,     "w") == 0 )
  587.             {
  588.                 if ( argc >= 3 )
  589.                 {
  590.                     uint wraplen = 0;
  591.                     sscanf( argv[2], "%d", &wraplen );
  592.                     tidyOptSetInt( tdoc, TidyWrapLen, wraplen );
  593.                     --argc;
  594.                     ++argv;
  595.                 }
  596.             }
  597.             else if ( strcasecmp(arg,  "version") == 0 ||
  598.                       strcasecmp(arg, "-version") == 0 ||
  599.                       strcasecmp(arg,        "v") == 0 )
  600.             {
  601.                 version( tdoc, prog );
  602.                 tidyRelease( tdoc );
  603.                 return 0;  /* success */
  604.  
  605.             }
  606.             else if ( strncmp(argv[1], "--", 2 ) == 0)
  607.             {
  608.                 if ( tidyOptParseValue(tdoc, argv[1]+2, argv[2]) )
  609.                 {
  610.                     /* Set new error output stream if setting changed */
  611.                     ctmbstr post = tidyOptGetValue( tdoc, TidyErrFile );
  612.                     if ( post && (!errfil || !samefile(errfil, post)) )
  613.                     {
  614.                         errfil = post;
  615.                         errout = tidySetErrorFile( tdoc, post );
  616.                     }
  617.  
  618.                     ++argv;
  619.                     --argc;
  620.                 }
  621.             }
  622.  
  623. #if SUPPORT_ACCESSIBILITY_CHECKS
  624.             else if ( strcasecmp(arg, "access") == 0 )
  625.             {
  626.                 if ( argc >= 3 )
  627.                 {
  628.                     uint acclvl = 0;
  629.                     sscanf( argv[2], "%d", &acclvl );
  630.                     tidyOptSetInt( tdoc, TidyAccessibilityCheckLevel, acclvl );
  631.                     --argc;
  632.                     ++argv;
  633.                 }
  634.             }
  635. #endif
  636.  
  637.             else
  638.             {
  639.                 uint c;
  640.                 ctmbstr s = argv[1];
  641.  
  642.                 while ( c = *++s )
  643.                 {
  644.                     switch ( c )
  645.                     {
  646.                     case 'i':
  647.                         tidyOptSetInt( tdoc, TidyIndentContent, TidyAutoState );
  648.                         if ( tidyOptGetInt(tdoc, TidyIndentSpaces) == 0 )
  649.                             tidyOptResetToDefault( tdoc, TidyIndentSpaces );
  650.                         break;
  651.  
  652.                     /* Usurp -o for output file.  Anyone hiding end tags?
  653.                     case 'o':
  654.                         tidyOptSetBool( tdoc, TidyHideEndTags, yes );
  655.                         break;
  656.                     */
  657.  
  658.                     case 'u':
  659.                         tidyOptSetBool( tdoc, TidyUpperCaseTags, yes );
  660.                         break;
  661.  
  662.                     case 'c':
  663.                         tidyOptSetBool( tdoc, TidyMakeClean, yes );
  664.                         break;
  665.  
  666.                     case 'b':
  667.                         tidyOptSetBool( tdoc, TidyMakeBare, yes );
  668.                         break;
  669.  
  670.                     case 'n':
  671.                         tidyOptSetBool( tdoc, TidyNumEntities, yes );
  672.                         break;
  673.  
  674.                     case 'm':
  675.                         tidyOptSetBool( tdoc, TidyWriteBack, yes );
  676.                         break;
  677.  
  678.                     case 'e':
  679.                         tidyOptSetBool( tdoc, TidyShowMarkup, no );
  680.                         break;
  681.  
  682.                     case 'q':
  683.                         tidyOptSetBool( tdoc, TidyQuiet, yes );
  684.                         break;
  685.  
  686.                     default:
  687.                         unknownOption( tdoc, c );
  688.                         break;
  689.                     }
  690.                 }
  691.             }
  692.  
  693.             --argc;
  694.             ++argv;
  695.             continue;
  696.         }
  697.  
  698.         if ( argc > 1 )
  699.         {
  700.             htmlfil = argv[1];
  701.             if ( tidyOptGetBool(tdoc, TidyEmacs) )
  702.                 tidyOptSetValue( tdoc, TidyEmacsFile, htmlfil );
  703.             status = tidyParseFile( tdoc, htmlfil );
  704.         }
  705.         else
  706.         {
  707.             htmlfil = "stdin";
  708.             status = tidyParseStdin( tdoc );
  709.         }
  710.  
  711.         if ( status >= 0 )
  712.             status = tidyCleanAndRepair( tdoc );
  713.  
  714.         if ( status >= 0 )
  715.             status = tidyRunDiagnostics( tdoc );
  716.  
  717.         if ( status > 1 ) /* If errors, do we want to force output? */
  718.             status = ( tidyOptGetBool(tdoc, TidyForceOutput) ? status : -1 );
  719.  
  720.         if ( status >= 0 && tidyOptGetBool(tdoc, TidyShowMarkup) )
  721.         {
  722.             if ( tidyOptGetBool(tdoc, TidyWriteBack) && argc > 1 )
  723.                 status = tidySaveFile( tdoc, htmlfil );
  724.             else
  725.             {
  726.                 ctmbstr outfil = tidyOptGetValue( tdoc, TidyOutFile );
  727.                 if ( outfil )
  728.                     status = tidySaveFile( tdoc, outfil );
  729.                 else
  730.                     status = tidySaveStdout( tdoc );
  731.             }
  732.         }
  733.  
  734.         contentErrors   += tidyErrorCount( tdoc );
  735.         contentWarnings += tidyWarningCount( tdoc );
  736.         accessWarnings  += tidyAccessWarningCount( tdoc );
  737.  
  738.         --argc;
  739.         ++argv;
  740.  
  741.         if ( argc <= 1 )
  742.             break;
  743.     }
  744.  
  745.     if (!tidyOptGetBool(tdoc, TidyQuiet) &&
  746.         errout == stderr && !contentErrors)
  747.         fprintf(errout, "\n");
  748.  
  749.     if (contentErrors + contentWarnings > 0 && 
  750.          !tidyOptGetBool(tdoc, TidyQuiet))
  751.         tidyErrorSummary(tdoc);
  752.  
  753.     if (!tidyOptGetBool(tdoc, TidyQuiet))
  754.         tidyGeneralInfo(tdoc);
  755.  
  756.     /* called to free hash tables etc. */
  757.     tidyRelease( tdoc );
  758.  
  759.     /* return status can be used by scripts */
  760.     if ( contentErrors > 0 )
  761.         return 2;
  762.  
  763.     if ( contentWarnings > 0 )
  764.         return 1;
  765.  
  766.     /* 0 signifies all is ok */
  767.     return 0;
  768. }
  769.  
  770.